package com.agadmin.common;


import com.agadmin.config.CustomUser;
import com.agadmin.entity.user.Users;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.*;

@Slf4j
@Component
public class JWTUtil {

    //token有效时长30分钟
    private static Long EXPIRE;
    //token的密钥
    private static String SECRET;
    //refresh-expire续期过期时间
    private static Long REFRESHEXPIRE;

    @Value("${jwt.expire}")
    public void setExpire(Long expire) {
        JWTUtil.EXPIRE = expire * 1000;
    }

    @Value("${jwt.secret}")
    public void setSecret(String secret) {
        JWTUtil.SECRET = secret;
    }

    @Value("${jwt.refresh-expire}")
    public void setRefreshExpire(Long refreshExpire) {
        JWTUtil.REFRESHEXPIRE = refreshExpire;
    }

//    @Autowired
//    private RedisTemplate redisTemplate;
//
//    @Autowired
//    private RedisUtil redisUtil2;
//
//    private static RedisUtil redisUtil;

//    @PostConstruct
//    public void init() {
//        JWTUtil.redisUtil = redisUtil2;
//    }

    public static String createToken(CustomUser user, String userId, String userName) throws UnsupportedEncodingException {
        //        //token过期时间
        Date date = new Date(System.currentTimeMillis() + EXPIRE);

        //Date now = new Date();
        long now = System.currentTimeMillis();

        //jwt的header部分
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        //使用jwt的api生成token
        String token = JWT.create()
                .withHeader(map)
                .withClaim("userId", userId)//私有声明
                .withClaim("username",userName).
                withClaim("password",user.getSysUser().getPassword())
                .withClaim("authorization",user.getAuthorities().stream()
                        .map(GrantedAuthority::getAuthority).toList())
                .withExpiresAt(date)//过期时间
                .withIssuedAt(new Date(now))//签发时间
                .sign(Algorithm.HMAC256(SECRET));//签名

        return token;
    }

    //校验token的有效性，1、token的header和payload是否没改过；2、没有过期
    public static boolean verify(String token) {
        try {
            //解密
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
            verifier.verify(token);
            return true;
        } catch (TokenExpiredException e) {
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isJwtExpired(String token) {
        /**
         * @desc 判断token是否过期
         * @author lj
         */
        try {
            DecodedJWT decodeToken = JWT.decode(token);
            return decodeToken.getExpiresAt().before(new Date());
        } catch (Exception e) {
            return true;
        }
    }

    //无需解密也可以获取token的信息
    public static String getUserId(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("userId").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    //无需解密也可以获取token的信息
    public static String getAccessToken(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return String.valueOf(jwt.getIssuedAt().getTime() / 1000);
        } catch (JWTDecodeException e) {
            return "";
        }
    }

    public static DecodedJWT parseToken(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt;
        } catch (JWTDecodeException e) {
            return null;
        }
    }


    public static CustomUser toUser(DecodedJWT jwt){
        Map<String, Claim> claims = jwt.getClaims();
        Users users = new Users();
        users.setUserName(claims.get("username").asString());
        users.setPassword(claims.get("password").asString());
        String userId = claims.get("userId").asString();
        users.setId(userId);
        List<GrantedAuthority> author=claims.get("authorization").asList(GrantedAuthority.class);
        if(author.size()==0){
            return new CustomUser(users,Collections.emptyList());
        }
        return new CustomUser(users, author);

//        return User
//                .withUsername(claims.get("username").asString())
//                .password("****")
//                .authorities(claims.get("authorization").asArray(String.class))
//                .build();
    }

}